Managing a cross-table from the script

If setting table visual resources are not enough, one can use the script for detailed settings for the appearance of the table. The "Cross-table" object has the following events:

Event Description
OnAfterPrint Event is called after printing a table.
OnBeforePrint Event is called before printing a table.
OnCalcHeight Event is called before calculating length of a row in the table. The event handler can return either the required value of height, or "0" when the row needs to be hidden.
OnCalcWidth Event is called before calculating column’s width in a table. The event handler can return either the required value of width, or "0" when the column needs to be hidden.
OnPrintCell Event is called before displaying a table’s cell. The event handler can modify the cell’s design or its contents.
OnPrintColumnHeader Event is called before displaying a title of the table’s columns. The event handler can modify design or contents of the title’s cell.
OnPrintRowHeader Event is called before displaying a title of the table’s rows. The event handler can modify design or contents of the title’s cell.

It is convenient to use the following methods of the "Cross-table" object in events:

Method Description
function ColCount: Integer Returns the number of columns in a table.
function RowCount: Integer Returns the number of rows in a table.
function IsGrandTotalColumn
(Index: Integer): Boolean
Returns "True," if the column with specified number is the total one.
function IsGrandTotalRow
(Index: Integer): Boolean
Returns "True," if the row with specified number is a total one.
function IsTotalColumn
(Index: Integer): Boolean
Returns "True," if the column with specified number is a column with intermediate totals.
function IsTotalRow
(Index: Integer): Boolean
Returns "True," if the line with specified number is a line with intermediate totals.
procedure AddValue (const
Rows, Columns, Cells:
array of Variant)
Adds a value to the table.

Let us exemplify, how one can highlight the third column (in our example it is the "November 1999" date). To perform this, select a cross-table and create the OnPrintCell event’s handler:

procedure Cross1OnPrintCell(Memo: TfrxMemoView;

RowIndex, ColumnIndex, CellIndex: Integer;

RowValues, ColumnValues, Value: Variant);

begin

if ColumnIndex = 2 then

Memo.Color := clRed;

end;

We will see the following result:

To highlight a column title, create an "OnPrintColumnHeader" event’s handler:

procedure Cross1OnPrintColumnHeader(Memo: TfrxMemoView;

HeaderIndexes, HeaderValues, Value: Variant);

begin

if (VarToStr(HeaderValues[0]) = '1999') and

(VarToStr(HeaderValues[1]) = '11') then

Memo.Color := clRed;

end;

Result would appear as follows:

Let us explain how the scripts work. The "OnPrintCell" event handler is called before printing a cell included in the table’s body (when printing cells from the table title, either the "OnPrintColumnHeader," or the "OnPrintRowHeader" handler is called). At the same time, a link to the "Text" object, which represents a table’s cell ("Memo" parameter), and the cell’s "address" in two variants: the number of row, column and cell (the last is relevant, if your table contains multi-leveled cells) in the "RowIndex," "ColumnIndex," and "CellIndex" parameters respectively, are transmitted into the "OnPrintCell" handler. The "RowValues" and the "ColumnValues" parameters are the second variant of the "address." The "Value" parameter is the cell’s contents.

To specify an "address," you can use the second variant (RowValues, ColumnValues), since it is more convenient in the given case (as well as the first one (RowIndex, ColumnIndex)). In our case, it was necessary to highlight the third column; therefore, it would be more convenient to analyze the first variant. Since numbering of columns and rows begins with "0," the "ColumnIndex = 2" checking allows us to define the third column. One could do it in a different way, i.e. by analyzing the required column by its data (we need the 11th month of 1999):

procedure Cross1OnPrintCell(Memo: TfrxMemoView;

RowIndex, ColumnIndex, CellIndex: Integer;

RowValues, ColumnValues, Value: Variant);

begin

if (VarToStr(ColumnValues[0]) = '1999') and

(VarToStr(ColumnValues[1]) = '11') then

Memo.Color := clRed;

end;

Values, which are transferred in the "RowValues" and the "ColumnValues" parameters, are arrays of the "Variant" type with a zero base. The zero element is a value of the highest level of the table’s title; the first one is a value of the next level, etc. In our case, the "ColumnValues[0]" contains years, and the "ColumnValues[1]" contains months.

Why is "VarToStr" transformation necessary? This guarantees absence of mistakes during type conversion. When operating with the "Variant" type, Delphi attempts to automatically cast the strings to number format, which, in its turn, can lead to an error when attempting to cast the "Total" and "Grand Total'" columns’ values.

The "OnPrintColumnHeader" event handler is called during typing column title cells. The set of parameters is similar to the parameters of the "OnPrintCell" handler, although in this case the cell’s "address" (the "HeaderIndexes" and "HeaderValues" parameters) is transferred in a different way. The "HeaderValues" parameter returns the same values, as the "ColumnValues" and "RowValues" parameters in the "OnPrintCell" handler. The "HeaderIndexes" parameter is also an array of values of the "Variant" type, which contains an address of the title’s cell in a different form: the zero element is the serial number of the highest level of the table’s title, the first one is the number of the next level, etc. To make the principle of cells numbering clear, refer to the picture below:

In our case, it is more convenient to analyze the "HeaderValues" value, but one can write the following handler as well:

procedure Cross1OnPrintColumnHeader(Memo: TfrxMemoView;

HeaderIndexes, HeaderValues, Value: Variant);

begin

if (HeaderIndexes[0] = 0) and (HeaderIndexes[1] = 2) then

Memo.Color := clRed;

end;